#include <stdio.h>
#include <stdlib.h>

#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
#include <netinet/in.h>

#include <openssl/evp.h>
#include <openssl/rand.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>

#include <dirent.h>
#include <fcntl.h>

typedef short bool;
#define true 1
#define false 0

#define BUFLEN 1024
#define USERLEN 32
#define PSSWLEN 16
#define NONCELEN 8

#define HELP "Commands available:\n * !HELP --> Shows the command list\n * !QUIT --> Quit the program\n * !LIST --> Shows the file list\n * !UPLD --> Uploads the file specified as argument\n * !DWLD --> Downloads the file specified as argument\n"

struct client{
	int id_sck;
	char username[USERLEN];
	struct sockaddr_in addr;
	unsigned char sharedkey[EVP_MAX_KEY_LENGTH];
	int protocol_step;
	unsigned char server_nonce[NONCELEN];
	unsigned char client_nonce[NONCELEN];
	struct client* next;
};

struct reg_client{
	char username[USERLEN];
	char password[PSSWLEN];
	struct reg_client* next;
};

void error(const char* msg);
char* str_trim(char* stringa);
void create_nonce(unsigned char *buf);
void printbyte(char b);
void printH(char* k,int len);
void write_file(char *in,char *file,int len);
void read_file(char *out,char *file,int len);
int file_len(char *file);
void select_random_key();
void encrypt_ctx_init(EVP_CIPHER_CTX* ctx, char* key, int key_size);
void decrypt_ctx_init(EVP_CIPHER_CTX* ctx, char* key, int key_size);
int encrypt(unsigned char* key, int keylen, unsigned char* ciphertext, int pt_len, unsigned char* plaintext);
int decrypt(unsigned char* key, int keylen, unsigned char* ciphertext, int ct_len, unsigned char* plaintext);
void TCP_send_enc_msg(unsigned char* key, int keylen,int sk,char* msg, int msglen);
char* TCP_recv_enc_msg(unsigned char* key, int keylen,int sk,int* msgsize);
int block_size();
void sgets(char * buf, int len);
unsigned char* compute_hash(char* plaintext, int pt_len,char* alg);
int hash_size(char* alg);
//TCP
void TCP_init(int* sk, struct sockaddr_in* sst,const char* addr,int port);
void TCP_connect(int sk,struct sockaddr_in* sst);
void TCP_bind(int sk, struct sockaddr_in* sst);
void TCP_listen(int sk,int n);
void TCP_accept(int sk,int* cl,struct sockaddr_in* clnt,socklen_t* len);
int TCP_send(int sk,void* msg,int len);
int TCP_recv(int sk,void* msg,int len);
void TCP_close(int sk);

void ins_list(struct client** list, struct client* elem);
int rmID_list(struct client** list,int id_sck,char* usr);
struct client* checkID_list(struct client* list,int id_sck);
int checkUsername_list(struct client* list,char* usr);
struct reg_client* checkUsr_list(struct reg_client* list,char* usr,char* pssw);
struct reg_client* generate_reg_client_list(char* filename);

//USER'S COMMAND
char* ls(char* name);
bool find_file(char dir_name[], char file_name[]);
void receive_enc_file(char* receiver_file, unsigned char* key, int keylen, int sk);
void send_enc_file(char* sender_file, unsigned char* key, int keylen, int sk);

